package com.sti.framework.models.Aps.controller;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.stream.CollectorUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sti.framework.core.controller.BaseController;
import com.sti.framework.core.web.ResponseBodyEntity;
import com.sti.framework.models.Aps.data.*;
import com.sti.framework.models.Aps.mapper.ApsMonthPlanMoMapper;
import com.sti.framework.models.Aps.mapper.ApsParameterMapper;
import com.sti.framework.models.Aps.mapper.ApsTeamCalendarInfoMapper;
import com.sti.framework.models.Aps.service.ApsModelInfoService;
import com.sti.framework.models.Aps.service.ApsMonthPlanMoResultService;
import com.sti.framework.models.Aps.service.ApsMonthPlanMoService;
import io.swagger.models.auth.In;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/Api/MonthPlanMo")
public class ApsMonthPlanMoController extends BaseController<ApsMonthPlanMoMapper, ApsMonthPlanMo, ApsMonthPlanMoWhere> {

    @Resource
    private ApsMonthPlanMoService apsMonthPlanMoService;
    @Resource
    private ApsModelInfoService apsModelInfoService;
    @Resource
    private ApsParameterMapper apsParameterMapper;
    @Resource
    private ApsTeamCalendarInfoMapper apsTeamCalendarInfoMapper;
    @Resource
    private ApsMonthPlanMoResultService apsMonthPlanMoResultService;

    @PostMapping("/init")
    public ResponseBodyEntity basicsDataInit(@RequestBody ApsMonthPlanMoWhere apsMonthPlanMoWhere) {
        apsMonthPlanMoResultService.remove(new LambdaQueryWrapper<>());
        LambdaQueryWrapper<ApsMonthPlanMo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotEmpty(apsMonthPlanMoWhere.getProductCode())) {
            lambdaQueryWrapper.eq(ApsMonthPlanMo::getProductCode, apsMonthPlanMoWhere.getProductCode());
        }
        lambdaQueryWrapper.last(" ORDER BY priority_value ASC," +
                "CASE WHEN date_complete IS NULL OR date_complete = '' THEN 1 ELSE 0 END ASC," +
                "CASE WHEN date_delivery IS NULL OR date_delivery = '' THEN 1 ELSE 0 END ASC ");
        //月订单数据
        List<ApsMonthPlanMo> moList = apsMonthPlanMoService.list(lambdaQueryWrapper);
        //获取模具数据
        LambdaQueryWrapper<ApsModelInfo> apsModelInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        apsModelInfoLambdaQueryWrapper.orderByAsc(ApsModelInfo::getCode);
        List<ApsModelInfo> modelList = apsModelInfoService.list(apsModelInfoLambdaQueryWrapper);
        //获取动态参数
        List<ApsParameter> parameterAll = apsParameterMapper.getParameterAll();
        try {
            Map<String, ApsParameter> stringApsParameterMap = initParameterConfig(parameterAll);
            //获取休息日
            LambdaQueryWrapper<ApsTeamCalendarInfo> apsTeamCalendarInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
            apsTeamCalendarInfoLambdaQueryWrapper.eq(ApsTeamCalendarInfo::getMonth, LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM")));
            List<ApsTeamCalendarInfo> apsTeamCalendarInfoList = apsTeamCalendarInfoMapper.selectList(apsTeamCalendarInfoLambdaQueryWrapper);
            //记录日历数据
            List<ScheduleMonthModel> scheduleMonthModelList = new ArrayList<>();
            //化学元素分组
            Map<String, List<ApsMonthPlanMo>> apsMonthPlanGroupMap = new LinkedHashMap<>();
            for (ApsMonthPlanMo apsMonthPlanMo : moList) {
//                //将化学元素字符串进行拆解
//                getApsMaterialInfo(apsMonthPlanMo);
//                for (Map.Entry<String, List<ApsMonthPlanMo>> groupEntry : apsMonthPlanGroupMap.entrySet()) {
//                    List<ApsMonthPlanMo> entryList = groupEntry.getValue();
//                    boolean comparisonChemical = getComparisonChemical(entryList.get(0), apsMonthPlanMo);
//                    if (comparisonChemical) {
//                        apsMonthPlanMo.setIsPutGroupMap(1);
//                        entryList.add(apsMonthPlanMo);
//                        break;
//                    }
//                }
//                //如果没有找寻到map组中相似材料则新开一个组
//                if (apsMonthPlanMo.getIsPutGroupMap() == null) {
//                    List<ApsMonthPlanMo> groupList = new ArrayList<>();
//                    apsMonthPlanMo.setIsPutGroupMap(1);
//                    groupList.add(apsMonthPlanMo);
//                    apsMonthPlanGroupMap.put(UUID.randomUUID().toString(), groupList);
//                }
            }
            Calendar calendar = Calendar.getInstance();
            //获取当月总天数
            int actualMaximum = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
            int nowDay = calendar.get(Calendar.DAY_OF_MONTH) + 1;
            //将天数转化为日历对象
            String ym = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM"));
            //获取白晚班日产量
            ApsParameter apsParameter = stringApsParameterMap.get("BANZU_DAY_CHANLIANG");
            //白班日产量
            List<ApsParameterValue> dayYield = apsParameter.getApsParameterValueList().stream().filter(item -> item.getDescription().contains("白班")).collect(Collectors.toList());
            //晚班日产量
            List<ApsParameterValue> nightYield = apsParameter.getApsParameterValueList().stream().filter(item -> item.getDescription().contains("夜班")).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(dayYield)) {
                throw new RuntimeException("缺少日产量配置");
            }
            if (CollectionUtils.isEmpty(nightYield)) {
                throw new RuntimeException("缺少日产量配置");
            }
            //制造方式约束标识(常法辊约定数量)
            ApsParameter apsParameterCz = stringApsParameterMap.get("CHANGFAGUN_VALUE");
            //常法所在班次
            ApsParameter apsParameterCzType = stringApsParameterMap.get("BANCI_ROUTINE");
            //打结料类型
            List<ApsParameterValue> daJieParamList = stringApsParameterMap.get("DAJIE_RANGE").getApsParameterValueList();
            for (int i = nowDay; i <= actualMaximum; i++) {
                ScheduleMonthModel scheduleMonthModel = new ScheduleMonthModel();
                scheduleMonthModel.setMonthDayDate(LocalDate.parse(ym + "-" + (i >= 10 ? i : "0" + i), DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                //白班
                ScheduleDayModel scheduleDayModelSun = new ScheduleDayModel();
                //白班日产量范围
                scheduleDayModelSun.setDayMax(BigDecimal.valueOf(Float.parseFloat(dayYield.get(0).getParameterValueMax())));
                scheduleDayModelSun.setDayMin(BigDecimal.valueOf(Float.parseFloat(dayYield.get(0).getParameterValueMin())));
                //已用日产量
                scheduleDayModelSun.setUsedCapacity(BigDecimal.ZERO);
                //判断是否休息
                long sunRest = apsTeamCalendarInfoList.stream().filter(item -> item.getWorkDay().equals(scheduleMonthModel.getMonthDayDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))
                        && item.getTeamType().contains("白班")).count();
                //是否休息
                scheduleDayModelSun.setIsRest(sunRest > 0);
                //是否白班做常法
                scheduleDayModelSun.setRoutineNum(!apsParameterCzType.getParameterValue().contains("白班") ? 0 : Integer.parseInt(apsParameterCz.getParameterValue()));
                scheduleDayModelSun.setClassType(1);

                //夜班
                ScheduleDayModel scheduleDayModelNight = new ScheduleDayModel();
                //夜班日产量范围
                scheduleDayModelNight.setDayMax(BigDecimal.valueOf(Float.parseFloat(nightYield.get(0).getParameterValueMax())));
                scheduleDayModelNight.setDayMin(BigDecimal.valueOf(Float.parseFloat(nightYield.get(0).getParameterValueMin())));
                //已用日产量
                scheduleDayModelNight.setUsedCapacity(BigDecimal.ZERO);
                //判断是否休息
                long nightRest = apsTeamCalendarInfoList.stream().filter(item -> item.getWorkDay().equals(scheduleMonthModel.getMonthDayDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))
                        && item.getTeamType().contains("夜班")).count();
                //是否休息
                scheduleDayModelNight.setIsRest(nightRest > 0);
                //是否白班做常法
                scheduleDayModelNight.setRoutineNum(!apsParameterCzType.getParameterValue().contains("夜班") ? 0 : Integer.parseInt(apsParameterCz.getParameterValue()));
                scheduleDayModelNight.setClassType(2);
                //班次列表
                List<ScheduleDayModel> scheduleDayModelList = new ArrayList<>();
                scheduleDayModelList.add(scheduleDayModelSun);
                scheduleDayModelList.add(scheduleDayModelNight);
                scheduleMonthModel.setScheduleDayModelList(scheduleDayModelList);
//                scheduleMonthModel.setScheduleDayModelSun(scheduleDayModelSun);
//                scheduleMonthModel.setScheduleDayModelNight(scheduleDayModelNight);
                scheduleMonthModelList.add(scheduleMonthModel);
            }

            //高硬度
            List<String> tallHardnessKeyStrList = Arrays.asList("钢", "铬", "无限");
            List<String> bsHardnessKeyStrList = Collections.singletonList("贝氏");
            //寻找模具
            for (ApsMonthPlanMo apsMonthPlanMo : moList) {
                //硬度为空
                if(!StringUtils.isNotEmpty(apsMonthPlanMo.getHardness())){
                    apsMonthPlanMo.setBaseDataException("缺少硬度参数信息");
                    continue;
                }
                //获取最小硬度值
                apsMonthPlanMo.setMinHardness(Integer.parseInt(apsMonthPlanMo.getHardness().substring(0, apsMonthPlanMo.getHardness().indexOf("/"))));
                apsMonthPlanMo.setMaxHardness(Integer.parseInt(apsMonthPlanMo.getHardness().substring(
                        apsMonthPlanMo.getHardness().indexOf("/") + 1, apsMonthPlanMo.getHardness().indexOf("("))
                ));
                boolean finalTallHardnessFlag = isFinalTallHardnessFlag(apsMonthPlanMo, tallHardnessKeyStrList, bsHardnessKeyStrList);
                if (CollectionUtils.isEmpty(modelList)) {
                    apsMonthPlanMo.setBaseDataException("缺少匹配模具数据");
                } else {
                    //过滤出可使用的模具
                    List<ApsModelInfo> usableModelList = modelList.stream().filter(item -> {
                        //直径判断(模具直径小于工艺直接则不符合)
                        if (item.getDiameter() < Integer.parseInt(apsMonthPlanMo.getWorkmanshipDiameter())) {
                            return false;
                        }
                        //长度判断(模具长度小于工艺直接则不符合)
                        if (BigDecimal.valueOf(item.getLength()).compareTo(apsMonthPlanMo.getWorkmanshipLength()) < 0) {
                            return false;
                        }
                        //直径差
                        int computeDiameter = Integer.parseInt(apsMonthPlanMo.getWorkmanshipDiameter()) - item.getDiameter();
                        //长度差
                        int computeLength = BigDecimal.valueOf(item.getLength()).subtract(apsMonthPlanMo.getWorkmanshipLength()).intValue();
                        //高硬度 直径差0到10
                        if (finalTallHardnessFlag) {
                            if (computeDiameter > 10) {
                                return false;
                            }
                        } else {
                            //直径差0到15
                            if (computeDiameter > 15) {
                                return false;
                            }
                        }
                        return computeLength <= 20 && apsMonthPlanMo.getCastType().equals(item.getType());
                    }).collect(Collectors.toList());
                    //适用模具
                    apsMonthPlanMo.setUsableModelList(usableModelList);
                }
            }
            //第一轮优先级
            for (ApsMonthPlanMo apsMonthPlanMo : moList) {
                //存在异常信息则跳出
                if(StringUtils.isNotEmpty(apsMonthPlanMo.getBaseDataException()) || StringUtils.isNotEmpty(apsMonthPlanMo.getExecuteException())){
                    continue;
                }
                //未匹配到模具
                if (CollectionUtils.isEmpty(apsMonthPlanMo.getUsableModelList())) {
                    continue;
                }
                //完成日期
                if (apsMonthPlanMo.getDateComplete() == null) {
                    continue;
                }
                //交付日期
                if (apsMonthPlanMo.getDateDelivery() == null) {
                    continue;
                }
                //判断完成日期与交付日期是否符合优先级1的逻辑
                LocalDate nowFormat = LocalDate.parse(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM")) + "-01", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                LocalDate completeFormat = LocalDate.parse(apsMonthPlanMo.getDateComplete().format(DateTimeFormatter.ofPattern("yyyy-MM")) + "-01", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                LocalDate deliveryFormat = LocalDate.parse(apsMonthPlanMo.getDateDelivery() + "/01", DateTimeFormatter.ofPattern("yyyy/MM/dd"));
                if (completeFormat.isAfter(nowFormat) || completeFormat.isBefore(nowFormat)) {
                    continue;
                }
                if (deliveryFormat.isAfter(nowFormat) || deliveryFormat.isBefore(nowFormat)) {
                    continue;
                }
                //判断打结料范围
                for (ApsParameterValue apsParameterValue : daJieParamList) {
                    if (apsMonthPlanMo.getMaterialName().contains(apsParameterValue.getDescription())) {
                        apsMonthPlanMo.setIsDaJieFlag("true");
                        break;
                    }
                }
                //优先级计算
                //支数/磨具数量
                BigDecimal result1 = (apsMonthPlanMo.getWaitCnt() > apsMonthPlanMo.getUsableModelList().size() ?
                        BigDecimal.valueOf(apsMonthPlanMo.getWaitCnt()).divide(BigDecimal.valueOf(apsMonthPlanMo.getUsableModelList().size()), 1, RoundingMode.UP) : BigDecimal.ONE);
                //开箱天数+造型时间
                BigDecimal result2 = BigDecimal.valueOf(apsMonthPlanMo.getCastDays() + (StringUtils.isNotEmpty(apsMonthPlanMo.getIsDaJieFlag()) ? 4 : 1));
                BigDecimal result3 = result1.subtract(result2).add(BigDecimal.ONE);
                long result4 = actualMaximum - nowDay;
                //加工周期
                apsMonthPlanMo.setPeriodDay(result3);
                //本月剩余周期
                apsMonthPlanMo.setResiduePeriodDay(Integer.parseInt(String.valueOf(result4)));
                //重新设置优先级
                apsMonthPlanMo.setPriorityValue(apsMonthPlanMo.getPeriodDay().compareTo(BigDecimal.valueOf(apsMonthPlanMo.getResiduePeriodDay())) <= 0 ? 1 : apsMonthPlanMo.getPriorityValue());
            }
            //1级订单
            List<ApsMonthPlanMo> monthPlanMoListFirst = moList.stream().filter(item -> item.getPriorityValue() != null && item.getPriorityValue() == 1
                    && StringUtils.isEmpty(item.getBaseDataException())
                    && StringUtils.isEmpty(item.getExecuteException())).collect(Collectors.toList());
            //排产结果集
            List<ApsMonthPlanMoResult> apsMonthPlanMoResultList = new ArrayList<>();
            //循环日历
            for (ScheduleMonthModel scheduleMonthModel : scheduleMonthModelList) {
                for (ScheduleDayModel scheduleDayModel : scheduleMonthModel.getScheduleDayModelList()) {
                    //循环订单
                    for (ApsMonthPlanMo apsMonthPlanMo : monthPlanMoListFirst) {
                        if(apsMonthPlanMo.getWaitCnt() == 0){
                            continue;
                        }
                        if("CWP450730".equals(apsMonthPlanMo.getProductCode())){
                            System.out.println("123");
                        }
                        //创建排产结果月订单实体类
                        ApsMonthPlanMoResult apsMonthPlanMoResult = new ApsMonthPlanMoResult();
                        BeanUtils.copyProperties(apsMonthPlanMo, apsMonthPlanMoResult);
                        apsMonthPlanMoResult.setId(null);
                        //筛选是否当前可以释放获取空闲中的模具
                        List<ApsModelInfo> apsModelInfoList = apsMonthPlanMo.getUsableModelList().stream().filter(item ->
                                "空闲中".equals(item.getStatus()) || scheduleMonthModel.getMonthDayDate().isAfter(item.getReleaseTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate()) ||
                                        (DateUtil.format(item.getReleaseTime(), "yyyy-MM-dd").equals(scheduleMonthModel.getMonthDayDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))
                                                && item.getReleaseTimeGap().equals(scheduleDayModel.getClassType()))).collect(Collectors.toList());
                        if (CollectionUtils.isEmpty(apsModelInfoList)) {
                            continue;
                        }
                        //记录班次可用产量是否可进行排产
                        boolean isProductionFlag;
                        //可进行白班排产(已用产量 <= 最大容量)并且不休息
                        isProductionFlag = scheduleDayModel.getUsedCapacity().compareTo(scheduleDayModel.getDayMax()) <= 0 && !scheduleDayModel.getIsRest();
                        //常法是否可通行
                        if("常法".equals(apsMonthPlanMo.getCastType()) && isProductionFlag){
                            isProductionFlag = scheduleDayModel.getRoutineNum() > 0;
                        }
                        //进行排产逻辑
                        if (isProductionFlag) {
                            //可使用产量
                            BigDecimal usable = scheduleDayModel.getDayMax().subtract(scheduleDayModel.getUsedCapacity());
                            //根据可用产量计算可以生产多少支
                            BigDecimal productionNum = usable.divide(apsMonthPlanMo.getWeight(), 0, RoundingMode.DOWN);
                            if(productionNum.compareTo(BigDecimal.ZERO) == 0){
                                continue;
                            }
                            //可生产支数大于等于剩余支数
                            if (productionNum.compareTo(BigDecimal.valueOf(apsMonthPlanMo.getWaitCnt())) >= 0) {
                                //已排
                                apsMonthPlanMoResult.setScheduleCnt("常法".equals(apsMonthPlanMo.getCastType()) ?
                                        (apsMonthPlanMo.getWaitCnt() >= scheduleDayModel.getRoutineNum() ? scheduleDayModel.getRoutineNum() : apsMonthPlanMo.getWaitCnt())
                                        : apsMonthPlanMo.getWaitCnt());
                            } else {
                                //已排
                                apsMonthPlanMoResult.setScheduleCnt("常法".equals(apsMonthPlanMo.getCastType()) ?
                                        (productionNum.longValue() > scheduleDayModel.getRoutineNum() ? scheduleDayModel.getRoutineNum() : productionNum.longValue())
                                        : productionNum.longValue());
                            }
                            //待排
                            apsMonthPlanMoResult.setWaitCnt(apsMonthPlanMoResult.getWaitCnt() - apsMonthPlanMoResult.getScheduleCnt());
                            //已排
                            apsMonthPlanMoResult.setCastCnt(apsMonthPlanMoResult.getCastCnt() == null ? apsMonthPlanMoResult.getScheduleCnt() : apsMonthPlanMoResult.getCastCnt() + apsMonthPlanMoResult.getScheduleCnt());
                            //-------更正月订单原始数据
                            //剩余可生产常法支数
                            if ("常法".equals(apsMonthPlanMo.getCastType())) {
                                scheduleDayModel.setRoutineNum(scheduleDayModel.getRoutineNum() - apsMonthPlanMoResult.getCastCnt().intValue());
                            }
                            //原始数据已排
                            apsMonthPlanMo.setCastCnt(apsMonthPlanMoResult.getCastCnt());
                            //原始数据待排
                            apsMonthPlanMo.setWaitCnt(apsMonthPlanMoResult.getWaitCnt());
                            //消耗占用变更
                            //已使用容量
                            scheduleDayModel.setUsedCapacity(scheduleDayModel.getUsedCapacity().add(apsMonthPlanMoResult.getWeight().multiply(BigDecimal.valueOf(apsMonthPlanMoResult.getCastCnt()))));
                            //将模具标记已使用
                            List<ApsModelInfo> usableModelList = apsMonthPlanMo.getUsableModelList();
                            List<String> usedModeStrList = new ArrayList<>();
                            for (int i = 0; i < usableModelList.size(); i++) {
                                if (i + 1 > apsMonthPlanMoResult.getScheduleCnt()) {
                                    break;
                                }
                                ApsModelInfo apsModelInfo = usableModelList.get(i);
                                apsModelInfo.setStatus("使用中");
                                Calendar calendarNow = Calendar.getInstance();
                                calendarNow.add(Calendar.DAY_OF_MONTH, StringUtils.isNotEmpty(apsMonthPlanMo.getIsDaJieFlag()) ? 4 : 1);
                                //释放日期
                                apsModelInfo.setReleaseTime(calendarNow.getTime());
                                //释放班次
                                apsModelInfo.setReleaseTimeGap(scheduleDayModel.getClassType());
                                //记录使用模具code
                                usedModeStrList.add(apsModelInfo.getCode());
                            }
                            //班次
                            apsMonthPlanMoResult.setClassType(scheduleDayModel.getClassType());
                            //加工开始时间
                            apsMonthPlanMoResult.setScheduleDate(scheduleMonthModel.getMonthDayDate());
//                            apsModelInfoList
                            apsMonthPlanMoResult.setUseModelList(StringUtils.join(usedModeStrList,","));
                            apsMonthPlanMoResultList.add(apsMonthPlanMoResult);
                        }
                    }
                }
            }
            //保存排产
            apsMonthPlanMoResultService.saveBatch(apsMonthPlanMoResultList);
            return ResponseBodyEntity.success();
        } catch (Exception e) {
            //写入异常
            for (ApsMonthPlanMo apsMonthPlanMo : moList) {
                apsMonthPlanMo.setBaseDataException(e.getMessage());
            }
            apsMonthPlanMoService.saveBatch(moList);
            return ResponseBodyEntity.fail(ResponseBodyEntity.ResponseStatus.FAIL, "排程出现错误");
        }
    }

    /**
     * 高硬度与贝氏体判断
     */
    private static boolean isFinalTallHardnessFlag(ApsMonthPlanMo apsMonthPlanMo, List<String> tallHardnessKeyStrList, List<String> bsHardnessKeyStrList) {
        boolean tallHardnessFlag = false;
        //高硬度
        for (String typeStr : tallHardnessKeyStrList) {
            tallHardnessFlag = apsMonthPlanMo.getMaterialName().contains(typeStr) && apsMonthPlanMo.getMinHardness() >= 75;
        }
        //贝氏体
        for (String typeStr : bsHardnessKeyStrList) {
            tallHardnessFlag = apsMonthPlanMo.getMaterialName().contains(typeStr) && apsMonthPlanMo.getMinHardness() >= 70;
        }
        return tallHardnessFlag;
    }

    /**
     * 处理化学元素 (字符串类型)
     */
    private static void getApsMaterialInfo(ApsMonthPlanMo apsMonthPlanMo) throws Exception {
        if(StringUtils.isNotEmpty(apsMonthPlanMo.getBomData())){
            //计算化学元素值
            List<String> bomStrList = new ArrayList<>();
            String[] bomStrArray = apsMonthPlanMo.getBomData().split(" {4}");
            for (String str : bomStrArray) {
                bomStrList.add(str.trim());
            }
            apsMonthPlanMo.setBomDataStrList(bomStrList);
            //将化学元素key与最大值拆分出
            Map<String, String> hxMap = new HashMap<>();
            for (String hxStr : bomStrList) {
                hxMap.put(hxStr.substring(0, hxStr.indexOf("：")), hxStr.substring(hxStr.lastIndexOf("/") + 1));
            }
            apsMonthPlanMo.setBomDataMap(hxMap);
        }
    }

    /**
     * 化学元素相似分组判断
     */
    private static boolean getComparisonChemical(ApsMonthPlanMo source, ApsMonthPlanMo target) {
        List<String> hxGroupList = Arrays.asList("Ni", "Cr", "Mo", "V", "W");
        //获取化学元素
        Map<String, String> bomDataMapSource = source.getBomDataMap();
        Map<String, String> bomDataMapTarget = target.getBomDataMap();
        //记录判断方向，例如：值全比源数据大或者比源数据全小
        Integer compareToVal = null;
        boolean isGroup = true;
        for (String hxStr : hxGroupList) {
            BigDecimal hxValSource = BigDecimal.valueOf(Double.parseDouble(bomDataMapSource.get(hxStr)));
            BigDecimal hxValTarget = BigDecimal.valueOf(Double.parseDouble(bomDataMapTarget.get(hxStr)));
            //初次判断
            if (compareToVal == null) {
                if (hxValSource.compareTo(hxValTarget) >= 0) {
                    compareToVal = 0;
                } else {
                    compareToVal = -1;
                }
            } else {
                if (compareToVal == 0) {
                    if (hxValSource.compareTo(hxValTarget) < 0) {
                        isGroup = false;
                    }
                } else {
                    if (hxValSource.compareTo(hxValTarget) >= 0) {
                        isGroup = false;
                    }
                }
            }
        }
        return isGroup;
    }

    /**
     * 动态参数初始化
     */
    public Map<String, ApsParameter> initParameterConfig(List<ApsParameter> apsParameterList) throws Exception {
        Map<String, ApsParameter> apsParameterMap = new HashMap<>();
        //获取班组日产量配置
        List<ApsParameter> dayCapacity = apsParameterList.stream().filter(item -> "BANZU_DAY_CHANLIANG".equals(item.getParameterName())).collect(Collectors.toList());
        if (dayCapacity.isEmpty()) {
            throw new Exception("缺少班组日产量动态参数配置");
        }
        //获取制造方式约束标识
        List<ApsParameter> capacityValue = apsParameterList.stream().filter(item -> "CHANGFAGUN_VALUE".equals(item.getParameterName())).collect(Collectors.toList());
        if (capacityValue.isEmpty()) {
            throw new Exception("缺少制造方式约束标识动态参数配置");
        }
        //获取常驻发所在班次约束
        List<ApsParameter> czConfig = apsParameterList.stream().filter(item -> "BANCI_ROUTINE".equals(item.getParameterName())).collect(Collectors.toList());
        if (czConfig.isEmpty()) {
            throw new Exception("缺少班次做常法约束动态参数配置");
        }
        List<ApsParameter> daJieConfig = apsParameterList.stream().filter(item -> "DAJIE_RANGE".equals(item.getParameterName())).collect(Collectors.toList());
        if (daJieConfig.isEmpty()) {
            throw new Exception("缺少打结料范围动态参数配置");
        }
        apsParameterMap.put("BANZU_DAY_CHANLIANG", dayCapacity.get(0));
        apsParameterMap.put("CHANGFAGUN_VALUE", capacityValue.get(0));
        apsParameterMap.put("BANCI_ROUTINE", czConfig.get(0));
        apsParameterMap.put("DAJIE_RANGE", daJieConfig.get(0));
        return apsParameterMap;
    }
}
